using DG.Tweening;
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
using UnityEngine.UI;
using Object = System.Object;
using AppTableUtils;
using System.Data;
using System.IO;
using OfficeOpenXml.FormulaParsing.Excel.Functions.Logical;
using UnityEngine.Serialization;
using TMPro;    


public class DialogManager : MonoBehaviour
{
    private bool dbg = false;

    [Header("选项动态尺寸")] public bool use_dynamic_choice_type = true;

    [Header("模板变量转换")]
    public bool use_template_translator = true;
    
    [Header("使用翻译功能")]
    public bool use_translator_manager = false;

    GameObject _dialog_canvas_obj;
    Transform _dialog_canvas_trans;

    [Header("对话画布")]
    public Transform dialog_canvas_trans;

    void _auto_set_dialog_canvas_trans()
    {
        if (dialog_canvas_trans != null)
            return;
        
        if (_dialog_canvas_trans == null)
        {
            _dialog_canvas_obj = BdTools.get_game_object_by_path("/DialogCanvas", raise_error: true);
            _dialog_canvas_trans = _dialog_canvas_obj.transform;
        }
        dialog_canvas_trans = _dialog_canvas_trans;
    }

    public Dictionary<string, Vector2> screen_positions = new Dictionary<string, Vector2>
    {
        {
            "left", BdTools.get_position_by_screen_scale(0.2f, 0.5f)
        },
        {
            "right", BdTools.get_position_by_screen_scale(0.8f, 0.5f)
        }
    };

    [FormerlySerializedAs("dialog_csv")] public DataTable dialog_dt;

    public GameObject dialog_canvas_obj
    {
        get
        {
            return dialog_canvas_trans.gameObject;
        }
    }

    public static DialogManager instance;

    public delegate void EventListener(String msg);

    private Dictionary<string, EventListener> eventListeners = new Dictionary<string, EventListener>();

    int current_dialog_id = 1;
    private int next_dialog_id = 1;
    DataRow current_row;
    private bool stop_next = false;
    private bool is_show_content = false;

    private void Awake()
    {
        if (dbg)
            BdUtils.log(" --- on DialogManager.Awake!");
        if (instance != null)
            Destroy(this);
        instance = this;
    }

    // [Header("对话表文件名")]
    // public string conversation_file_name;
    
    [Header("默认对话表文件名")]

    public string _file_name = null;

    public string dialog_dir_path  // 对话文件夹路径
    {
        get
        {
            return BdUtils.join(BdUtils.data_table_dir_path, "dialogs");
        }
    }

    [Header("打印Debug信息")]
    public bool show_debug_info = false;

    public void load_csv(string file_name = null)
    {
        if (BdUtils.is_null(file_name))
        {
            // BdPackage.BdUtils.assert(_file_name, "DialogManager._file_name不能为空!");
            if (BdUtils.is_null(_file_name))
            {
                // _file_name = BdUtils.join(BdUtils.data_table_dir_path, "dialogs", "test_dialog.csv");
                // _file_name = BdUtils.join(BdUtils.data_table_dir_path, "dialogs", "dialog_tree.csv");
                _file_name = BdUtils.join(dialog_dir_path, "dialog_tree_1.xlsx");
            }
            else if (!_file_name.StartsWith(dialog_dir_path))
            {
                _file_name = BdUtils.join(dialog_dir_path, _file_name);
            }

            // var (my_file_name, my_extension) = BdUtils.get_file_name_and_extension(_file_name);
            // string dir_path = Path.GetDirectoryName(_file_name);
            // string dir_name = Path.GetFileName(dir_path);
            // BdUtils.log($"~~~ dir_path: {dir_path}, dir_name: {dir_name}, my_file_name: {my_file_name}, my_extension: {my_extension}");

            // string table_name = "dialog_tree_1";
            // string table_path = BdUtils.join(dialog_dir_path, table_name);
            //
            // BdUtils.log($"*** is_exists_table: {TableUtils.is_exists_table(table_path)}");
            
            if (!BdTools.Flags.is_android_or_webgl)
                BdUtils.assert(BdUtils.exists_file(_file_name), $"对话文件不存在? `_file_name` path: {_file_name}");

            file_name = _file_name;
        }
        else
        {
            file_name = BdUtils.join(BdUtils.data_table_dir_path, "dialogs", file_name);
        }
        if (show_debug_info) BdPackage.BdUtils.log($"=== DialogManager load_csv file_name: {file_name}");
        dialog_dt = TableUtils.read_table(file_name, primary_key: "ID");
        
        if (show_debug_info) TableUtils.show_data_table(dialog_dt);
    }

    void play_animation_0(string msg)
    {
        BdUtils.log("====== on play_animation_0! msg:", msg);
    }
    void change_content_table(string msg)
    {
        BdUtils.log("====== on change_content_table! msg:", msg);

        var row = BdUtils.conv_json_to_dict(msg);
        string new_file_name = BdUtils.conv_to_string(row["params"]);
        load_csv(new_file_name);

        float t = 0.2f;  // [延迟/等待/休眠/timeout]t秒后执行
        DOTween.To(() => t, (x) => t = x, 0, t).OnComplete(
            () =>
            {
                instance.change_dialog_canvas_active_state();
                next_dialog();
            }
            );
    }
    
    void Start()
    {
        _auto_set_dialog_canvas_trans();

        BdTools.get_game_object_by_path("/EventSystem", raise_error: true);
        // BdUtils.assert(, "`EventSystem`不存在? 请手动创建一次`Canvas`!");
        // dialog_canvas_trans = ObjectPoolManager.instance.transform.Find("/DialogCanvas");
        choices_fixed_obj = BdTools.get_game_object_by_path("choices_fixed", dialog_canvas_obj);
        choices_dynamic_obj = BdTools.get_game_object_by_path("choices_dynamic", dialog_canvas_obj);
        BdUtils.assert(choices_fixed_obj, $"`choices_fixed_obj`为空?");
        BdUtils.assert(choices_dynamic_obj, "`choices_dynamic_obj`为空?");
        
        load_csv();

        // BdUtils.log("find dialog_canvas! obj_path:", BdTools.get_abs_path_by_obj(dialog_canvas_trans.gameObject));

        init_state();

        if (debug)
        {
            AddEventListener("play_animation_0", play_animation_0);
            AddEventListener("change_content_table", change_content_table);
        }
    }

    // Update is called once per frame
    private float delta_time__update_dialog;

    [Header("开启debug")]
    public bool debug = false;

    void Update()
    {
        if (!debug)
            return;

        delta_time__update_dialog += Time.deltaTime;

        if (Input.GetKeyDown(KeyCode.E))
        {
            change_dialog_canvas_active_state();
        }
        
        if (Input.GetKeyDown(KeyCode.Space) || Input.GetMouseButtonDown(0))
        {
            if (stop_next)
            {
                return;
            }
            
            if (next_dialog_id == 1 || delta_time__update_dialog >= 1f)
            {
                // BdUtils.log("~~~ next dialog!");                
                next_dialog();
                delta_time__update_dialog = 0;
            }
        }

        if (Input.GetKeyDown(KeyCode.A))
        {
            next_dialog(3);
        }
    }

    public void init_state()
    {
        current_row = null;
        next_dialog_id = current_dialog_id = 1;
        stop_next = false;
        is_show_content = false;
        delta_time__update_dialog = 0;

        BdTools.change_state_of_game_object(dialog_canvas_obj, state: false, self: false);
        // dialog_canvas_obj.SetActive(true);

        show_dialog(0);
        // next_dialog();
    }

    string try_get_translated_content(DataRow row)
    {
        string content = BdUtils.conv_to_string(row["content"]);;
        if (use_translator_manager)
        {
            BdUtils.assert(TranslatorManager.instance != null, "TranslatorManager.instance为null?");
            string _key_content = $"content_{TranslatorManager.instance.language}";
            BdUtils.assert(dialog_dt.Columns.Contains(_key_content), $"dialog_dt没有对应语言[{_key_content}]!");
            content = BdUtils.conv_to_string(row[_key_content]);;
        }
        return content;
    }

    public void next_dialog(int jump_to = BdUtils.DEFAULT_INT)
    {
        if (jump_to != BdUtils.DEFAULT_INT)
        {
            next_dialog_id = jump_to;
        }

        if (next_dialog_id == 0)
        {
            // 结束
            if (dbg)
                BdUtils.log("====== end dialog ======");
            exit_dialog_model();
            return;
        }

        // 判断是否应该暂停next_dialog
        if (stop_next)
        {
            if (dbg)
                BdTools.show_message_box(content: "请选择对话选项!", parent_trans: dialog_canvas_trans,
                    position: BdTools.ScreenPositions.center_bottom);
            return;
        }

        if (is_show_content)
        {
            if (dbg)
                BdTools.show_message_box(content: "话还没说完呢...", parent_trans: dialog_canvas_trans,
                    position: BdTools.ScreenPositions.center_bottom);
            return;
        }

        // BdUtils.log("~~~ is_active:", dialog_canvas_obj.activeInHierarchy);
        if (!dialog_canvas_obj.activeInHierarchy || next_dialog_id == 0)
        {
            // 结束
            // BdUtils.log("====== dialog is end! ======");
            return;
        }

        if (current_row == null)
        {
            current_row = TableUtils.get(dialog_dt, pk: next_dialog_id);
            if (current_row == null)
            {
                exit_dialog_model();
                return;
            }
            // BdUtils.assert(current_row, $"current_row不能为空! next_dialog_id: {next_dialog_id}");
        }

        // next_dialog_id = BdUtils.conv_to_int(current_row["next_id"]);

        current_dialog_id = next_dialog_id;
        next_dialog_id = BdUtils.conv_to_int(current_row["next_id"], -1); // `null`等非int值会解析为`-1`

        var id = BdUtils.conv_to_int(current_row["id"]);
        var role = BdUtils.conv_to_string(current_row["role"]);

        string content = try_get_translated_content(current_row);
        
        var position = BdUtils.conv_to_string(current_row["position"]);
        var portrait_path = BdUtils.conv_to_string(current_row["portrait"]);
        
        var options_string = BdUtils.conv_to_string(current_row["options"]);

        bool is_option;
        // is_option = BdUtils.conv_to_bool(current_row["is_option"]);

        List<DataRow> options = new List<DataRow>();

        // if (BdUtils.not_null(portrait_path))
        // {
        //     // dialog_canvas_obj;
        //     // dialog_canvas_trans;
        //     // var portrait_obj = BdTools.get_abs_path_by_obj();
        // }

        if (next_dialog_id == -1)
        {
            if (!BdUtils.is_null(options_string))
            {
                string[] options_array = options_string.Split(new char[]
                {
                    ','
                }, StringSplitOptions.RemoveEmptyEntries);
                
                // BdUtils.log($"~~~ options_array: {options_array}");

                foreach (string _option_id in options_array)
                {
                    // BdUtils.log("*** _option_id:", _option_id, "--- haha:", BdUtils.get_file_name_and_extension("haha"));
                    int option_id = BdUtils.conv_to_int(_option_id);
                    var option_row = TableUtils.get(dialog_dt, pk: option_id);
                    is_option = BdUtils.conv_to_bool(option_row["is_option"]);
                    BdUtils.assert(is_option, "options的id指向的不是option?");
                    options.Add(option_row);
                }
                
                // options = BdUtils.conv_obj_to_list
                // BdUtils.seq_path
                // BdUtils.conv_obj_to_list<int>()
            }

            else 
            {
                // --- 获取options
                // BdUtils.log("--- 获取options");
                is_option = true;
                while (is_option)
                {
                    next_dialog_id = current_dialog_id + 1;
                    current_dialog_id = next_dialog_id;
                    var option_row = TableUtils.get(dialog_dt, pk: next_dialog_id);
                    if (BdUtils.is_null(option_row))
                        break;
                    is_option = BdUtils.conv_to_bool(option_row["is_option"]);
                    if (is_option)
                    {
                        // BdUtils.log("~~~ next_dialog_id:", next_dialog_id, "~~~ is_option:", is_option);
                        options.Add(option_row);
                    }
                    else
                        break;
                }
            }
        }

        if (!BdUtils.is_null(position))
        {
            int dtype;
            if (position == "left" || position == "l")
            {
                dtype = 1;
            }
            else
            {
                dtype = 2;
            }

            if (BdUtils.not_null(options))
            {
                stop_next = true;
                // BdUtils.log("------ stop_next, options.Count:", options.Count);
            }
            
            var _event = BdUtils.conv_to_string(current_row["event"]);
            var e_order = BdUtils.conv_to_int(current_row["e_order"], 0);

            List<int> ls_order = new List<int>
            {
                -1,
                0,
                1
            };
            BdUtils.assert(ls_order.Contains(e_order), $"`e_order`取值必须在{ls_order}之中!");

            if (BdUtils.not_null(_event))
            {
                BdUtils.log("****** e_order:", e_order, "| _event:", _event);
                if (e_order == -1)
                {
                    FireEvent(_event, BdUtils.conv_obj_to_json(TableUtils.conv_row_to_dc(current_row)));
                }
            }

            show_dialog(dtype: dtype, content: content, options: options, portrait_name: portrait_path);

            if (BdUtils.not_null(_event))
            {
                if (e_order == 1)
                {
                    FireEvent(_event, BdUtils.conv_obj_to_json(TableUtils.conv_row_to_dc(current_row)));
                }
            }
        }

        // BdUtils.log("--- dialog --- ", "role:", role, ", content:", content, "--- id:", id, ", next_dialog_id:", next_dialog_id);
        current_row = null;
        options = null;
    }
    
    private GameObject choices_fixed_obj;
    private GameObject choices_dynamic_obj;

    public void show_dialog(int dtype = 1, string content = null, List<DataRow> options = null, string portrait_name = "")
    {
        // string choice_type = "fixed";
        string choice_type = use_dynamic_choice_type ? "dynamic" : "fixed";
        int _dtype_b = dtype == 1 ? 2 : 1;

        int _dtype_a = dtype;
        if (dtype == 0)
            _dtype_a = 1;

        var dialog_a = BdTools.get_game_object_by_path($"dialog_{_dtype_a}", dialog_canvas_obj);
        var dialog_b = BdTools.get_game_object_by_path($"dialog_{_dtype_b}", dialog_canvas_obj);

        BdUtils.assert(dialog_a, "`dialog_a`为空?");
        BdUtils.assert(dialog_b, "`dialog_b`为空?");

        BdTools.change_state_of_game_object(choices_fixed_obj);
        BdTools.change_state_of_game_object(choices_dynamic_obj);

        dialog_b.SetActive(false);

        if (dtype == 0)
        {
            if (dbg)
                BdUtils.log("--- on dtype == 0!", dbg);
            // if(!BdUtils.is_null(dialog_a))
            dialog_a.SetActive(false);
            dialog_b.SetActive(false);
            return;
        }

        if (BdUtils.not_null(portrait_name))
        {
            var portrait_obj = BdTools.get_game_object_by_path("Image_Character", dialog_a);

            // string portrait_dir_path = BdUtils.join(BdUtils.streaming_data_dir_path, "portrait");
            // string portrait_path = BdUtils.join(portrait_dir_path, portrait_name);

            string portrait_path = BdTools.get_static_abs_file_path_on_all_platform(BdUtils.join("portrait", portrait_name));

            BdUtils.assert(BdUtils.exists_file(portrait_path), $"`portrait_name`[{portrait_name}]不存在? portrait_path: {portrait_path}");

            Image imageComponent = portrait_obj.GetComponent<Image>();
            RectTransform rectTransform = imageComponent.rectTransform;
            Vector2 imageSize = rectTransform.sizeDelta;
            BdPackage.BdUtils.log("portrait_obj --- Image size: " + imageSize);

            BdTools.load_img_to_obj_sprite_renderer(portrait_obj, portrait_path, img_size: imageSize);
        }
        
        var next_button = BdTools.get_game_object_by_path("Chat/Button_Next", dialog_a);
        BdUtils.assert(next_button, "next_button为空?");
        next_button.SetActive(false);
        dialog_a.SetActive(true);

        if (content != null)
        {
            var text_comp = BdTools.get_component_in_obj_self_or_children<TMP_Text>(dialog_a);
            float duration = (float)(content.Length) / 15;
            // Ease easeType = Ease.Linear;
            is_show_content = true;
            
            if (use_template_translator && TranslatorManager.instance)
                content = TranslatorManager.instance.translate_template(content);
            
            Tweener tweener;
            tweener = DOTween.To(() => text_comp.text = "", x => text_comp.text = x.Replace("\\n", "\n"), content, duration)
                // .SetEase(easeType)
                .OnComplete(
                    () =>
                    {
                        // var text_comp_1 = BdTools.get_component_in_obj_self_or_children<TMP_Text>(choices_dynamic_obj);
                        // var image_comp_1 = BdTools.get_component_in_obj_self_or_children<Image>(choices_dynamic_obj);
                        // text_comp_1.enabled = false;
                        // image_comp_1.enabled = false;
                        
                        choices_fixed_obj.SetActive(true);
                        choices_dynamic_obj.SetActive(true);
                        
                        // text_comp_1.enabled = true;
                        // image_comp_1.enabled = true;

                        next_button.SetActive(true);
                        is_show_content = false;
                    }
                    );

            // tweener.timeScale = 0.2f;
            // tweener.Kill();
            
            float t = duration + 0.1f; // [延迟/等待/休眠/timeout]t秒后执行
            DOTween.To(() => t, (x) => t = x, 0, t).OnComplete(
                () =>
                {
                    choices_dynamic_obj.GetComponent<VerticalLayoutGroup>().childForceExpandWidth = true;
                    choices_dynamic_obj.GetComponent<VerticalLayoutGroup>().childForceExpandWidth = false;
                }
                );
        }

        if (!BdUtils.is_null(options))
        {
            for (var i = 0; i < options.Count; i++)
            {
                var option = options[i];
                // string content_i = BdUtils.conv_to_string(option["content"]);
                string content_i = try_get_translated_content(option);
                string o_event = BdUtils.conv_to_string(option["event"]);

                // BdUtils.log(" --- on option, content_i: ", content_i);

                string choice_i_path = BdUtils.unity_join(BdTools.get_abs_path_by_obj(dialog_canvas_obj),
                    $"choices_{choice_type}",
                    $"choice_{choice_type}_{i + 1}");

                var choice_i = BdTools.get_game_object_by_path(choice_i_path);
                BdUtils.assert(choice_i, $"choice_i为空? choice_i_path: {choice_i_path}");

                if (use_dynamic_choice_type)
                {
                    var text_comp = BdTools.get_component_in_obj_self_or_children<Text>(choice_i);
                    text_comp.text = content_i;

                    var old_color = text_comp.color;
                    // text_comp.color = new Color(0, 0, 0, 0);
                    text_comp.color = Color.white;
                    text_comp.DOColor(old_color, 2f);

                    float t = 0.5f; // [延迟/等待/休眠/timeout]t秒后执行
                    DOTween.To(() => t, (x) => t = x, 0, t).OnComplete(
                        () =>
                        {
                            choices_dynamic_obj.GetComponent<VerticalLayoutGroup>().childForceExpandWidth = true;
                            choices_dynamic_obj.GetComponent<VerticalLayoutGroup>().childForceExpandWidth = false;
                        }
                        );

                }
                else
                {
                    var text_comp = BdTools.get_component_in_obj_self_or_children<TMP_Text>(choice_i);
                    text_comp.text = content_i;
                }

                int jump_to = BdUtils.conv_to_int(option["next_id"]);

                // --- add call on button click
                var btn_comp = choice_i.transform.GetComponent<Button>();
                BdUtils.assert(btn_comp, "btn_comp不能为null!");
                btn_comp.onClick.RemoveAllListeners();
                btn_comp.onClick.AddListener(() =>
                {
                    // BdUtils.log(" *** OnClickChoiceBtn! content_i:", content_i, "--- o_event:", o_event);
                    FireEvent(o_event, BdUtils.conv_obj_to_json(TableUtils.conv_row_to_dc(option)));

                    stop_next = false;
                    is_show_content = false;
                    delta_time__update_dialog = 0;
                    next_dialog(jump_to: jump_to);
                });

                choice_i.SetActive(true);
            }
        }

        return;
    }

    public void enter_dialog_model()
    {
        dialog_canvas_trans.gameObject.SetActive(true);
        init_state();
        return;
    }

    public void exit_dialog_model()
    {
        init_state();
        dialog_canvas_trans.gameObject.SetActive(false);
        return;
    }

    public void change_dialog_canvas_active_state()
    {
        if (dialog_canvas_trans.gameObject.activeInHierarchy)
        {
            exit_dialog_model();
        }
        else
        {
            enter_dialog_model();
        }
    }

    public void AddEventListener(string envEvent, EventListener listener)
    {
        if (eventListeners.ContainsKey(envEvent))
        {
            BdUtils.assert(!eventListeners.ContainsValue(listener), "AddEventListener对同一个key增加了重复的value!");
            eventListeners[envEvent] += listener;
        }
        else
        {
            eventListeners[envEvent] = listener;
        }
    }

    public void RemoveEventListener(string envEvent, EventListener listener)
    {
        if (eventListeners.ContainsKey(envEvent))
        {
            eventListeners[envEvent] -= listener;
            if (eventListeners[envEvent] == null)
            {
                eventListeners.Remove(envEvent);
            }
        }
    }

    [Header("event对不上时是否报错")]
    public bool flag__raise_error_if_event_map_none = true;
    public void FireEvent(string envEvent, string msg)
    {
        if (BdUtils.is_null(envEvent))
            return;
        
        if (eventListeners.ContainsKey(envEvent))
        {
            eventListeners[envEvent](msg);
        }
        else
        {
            BdUtils.assert(!flag__raise_error_if_event_map_none, $" *** `envEvent[{envEvent}]`对应`row`为空? msg: {msg}");
        }
    }
}
